using System;
using System.ComponentModel;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.WowAddonStudio.FrameXml.Serialization.TypeConverters;
using NUnit.Framework;

namespace Microsoft.WowAddonStudio.FrameXml.Serialization.Tests.TypeConvertersTests
{
	[TestFixture]
	public sealed class TexCoordsTypeConverterTest
	{
		private const char listSeparator = ';';
		private static Regex insetStringRegex;
		private TypeConverter typeConverter;

		#region Setup/Teardown

		[TestFixtureSetUp]
		public void TestFixtureSetUp()
		{
			var sp = @"^(([-+]?[0-9]*\%DECIMALSEPARATOR%?[0-9]+);){3}(([-+]?[0-9]*\%DECIMALSEPARATOR%?[0-9]+);{0,1}){1}$";
			sp = sp.Replace("%DECIMALSEPARATOR%", CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);
			insetStringRegex = new Regex(sp, RegexOptions.Compiled);
		}

		[SetUp]
		public void SetUp()
		{
			typeConverter = new TexCoordsTypeConverter();
		}

		[TearDown]
		public void TearDown()
		{
		}

		#endregion

		[Test(Description = "")]
		public void Test_SimpleConvertTo()
		{
			var inset = new TexCoords {Left = 10.1f, Right = 20.1f, Top = 30.1f, Bottom = 40.1f};
			object convertTo = typeConverter.ConvertTo(null, CultureInfo.CurrentCulture, inset, typeof (string));
			Assert.IsNotNull(convertTo);
			Assert.IsInstanceOfType(typeof (string), convertTo);
			Assert.AreEqual(
				String.Format(CultureInfo.CurrentCulture, "{0}{4}{1}{4}{2}{4}{3}", inset.Left, inset.Right, inset.Top, inset.Bottom,
				              listSeparator), convertTo);

			convertTo = typeConverter.ConvertTo(null, CultureInfo.CurrentCulture, null, typeof (string));
			Assert.IsNotNull(convertTo);
			Assert.AreEqual(String.Empty, convertTo);
		}

		[Test(Description = "")]
		public void Test_SimpleConvertFrom()
		{
			var texCoords = new TexCoords {Left = 10.1f, Right = 20.1f, Top = 30.1f, Bottom = 40.1f};
			string insetString = String.Format(CultureInfo.CurrentCulture, "{0}{4}{1}{4}{2}{4}{3}", texCoords.Left, texCoords.Right,
			                                   texCoords.Top, texCoords.Bottom, listSeparator);
			Console.WriteLine(insetString);
			object convertFrom = typeConverter.ConvertFrom(null, CultureInfo.CurrentCulture, insetString);
			Assert.IsNotNull(convertFrom);
			Assert.IsInstanceOfType(typeof (TexCoords), convertFrom);
			texCoords = (TexCoords) convertFrom;
			Assert.AreEqual(10.1f, texCoords.Left);
			Assert.AreEqual(20.1f, texCoords.Right);
			Assert.AreEqual(30.1f, texCoords.Top);
			Assert.AreEqual(40.1f, texCoords.Bottom);
		}

		[Test(Description = "")]
		public void Test_ConvertFromSingleValue()
		{
			object convertFrom = typeConverter.ConvertFrom(null, CultureInfo.CurrentCulture, 10.ToString());
			Assert.IsNotNull(convertFrom);
			Assert.IsInstanceOfType(typeof(TexCoords), convertFrom);
			var texCoords = (TexCoords)convertFrom;
			Assert.AreEqual(10f, texCoords.Left);
			Assert.AreEqual(10f, texCoords.Right);
			Assert.AreEqual(10f, texCoords.Top);
			Assert.AreEqual(10f, texCoords.Bottom);

			convertFrom = typeConverter.ConvertFrom(null, CultureInfo.CurrentCulture, 10.1f.ToString());
			Assert.IsNotNull(convertFrom);
			Assert.IsInstanceOfType(typeof(TexCoords), convertFrom);
			texCoords = (TexCoords)convertFrom;
			Assert.AreEqual(10.1f, texCoords.Left);
			Assert.AreEqual(10.1f, texCoords.Right);
			Assert.AreEqual(10.1f, texCoords.Top);
			Assert.AreEqual(10.1f, texCoords.Bottom);
		}

		[Test(Description = "")]
		[ExpectedException(typeof (ArgumentException))]
		public void Test_SimpleConvertFromFailed()
		{
			typeConverter.ConvertFrom(null, CultureInfo.CurrentCulture, "441wer,erytrty");
		}

		[Test(Description = "")]
		[ExpectedException(typeof (NotSupportedException))]
		public void Test_SimpleConvertFromFromEmptyValue()
		{
			typeConverter.ConvertFrom(null, CultureInfo.CurrentCulture, null);
		}

		[Test(Description = "")]
		public void Test_InsetRegex()
		{
			var textValue = CreateTexCoordsString(100.1f, 20.2f,  100.3f,  200.4f);
			Assert.IsTrue(Match(textValue));

			textValue = CreateTexCoordsString(100.1f, 20.2f, 100.3f, 200.4f);
			textValue = textValue.Remove(textValue.Length - 1, 1);
			Assert.IsTrue(Match(textValue));

			textValue = CreateTexCoordsString(100.1f, 20.2f, 100.3f);
			Assert.IsFalse(Match(textValue));

			textValue = CreateTexCoordsString(100.1f, 20.2f);
			Assert.IsFalse(Match(textValue));

			textValue = "100.1,100.2,100.3|100.4";
			Assert.IsFalse(Match(textValue));
		}

		private static string CreateTexCoordsString(params float?[] values)
		{
			var builder = new StringBuilder();
	
			foreach (float? value in values)
			{
				if(value.HasValue)
				{
					builder.Append(value.Value.ToString(CultureInfo.CurrentCulture));
					builder.Append(listSeparator);
				}
			}
			return builder.ToString();
		}

		/// <summary>
		/// Matches the specified text.
		/// </summary>
		/// <param name="text">The text.</param>
		/// <returns></returns>
		private static bool Match(string text)
		{
			Match match = insetStringRegex.Match(text);
			return match.Success;
		}
	}
}